#include <check.h>
#include "test_cpu_info.h"

#include <signal.h>
#include "cpu_info.h"

/* Testeo de precondiciones */
START_TEST (test_null_path)
{
	CpuInfo info = cpu_info_new (NULL);
	info = cpu_info_destroy (info);
}
END_TEST

/* Testeo de funcionalidad */

static CpuInfo info; /* Compartida por los tests... */

START_TEST (test_no_cpuinfo_file)
{
	/* Debería andar todo bien si no existe el archivo 'cpuinfo' */
	info = cpu_info_new ("cpuinfo/nofile");

	/* y obtenemos 'Unknown' como marca y modelo */
	fail_unless (biseqcstr (info.type, "Unknown"));
	fail_unless (biseqcstr (info.model, "Unknown"));
}
END_TEST

START_TEST (test_cpuinfo_empty)
{
	/* Debería andar todo bien si el archivo 'cpuinfo' está vacío */
	info = cpu_info_new ("cpuinfo/emptyfile");

	/* y obtenemos 'Unknown' como marca y modelo */
	fail_unless (biseqcstr (info.type, "Unknown"));
	fail_unless (biseqcstr (info.model, "Unknown"));
}
END_TEST

START_TEST (test_cpuinfo_typeonly)
{
	/* Debería andar todo bien si hay marca pero no modelo */
	info = cpu_info_new ("cpuinfo/typeonly");

	/* y obtenemos 'Unknown' modelo, y la marca */
	fail_unless (biseqcstr (info.type, "Test type"));
	fail_unless (biseqcstr (info.model, "Unknown"));
}
END_TEST

START_TEST (test_cpuinfo_modelonly)
{
	/* Debería andar todo bien si hay modelo pero no marca */
	info = cpu_info_new ("cpuinfo/modelonly");

	/* y obtenemos 'Unknown' como marca, y el modelo */
	fail_unless (biseqcstr (info.type, "Unknown"));
	fail_unless (biseqcstr (info.model, "Test model"));
}
END_TEST

START_TEST (test_cpuinfo_type_and_model)
{
	/* Debería andar todo bien si el archivo 'cpuinfo' tiene marca y modelo */
	info = cpu_info_new ("cpuinfo/typemodel");

	/* y obtenemos la marca y modelo del archivo */
	fail_unless (biseqcstr (info.type, "Test type"));
	fail_unless (biseqcstr (info.model, "Test model"));
}
END_TEST

START_TEST (test_cpuinfo_model_and_type)
{
	/* Debería andar todo bien si el archivo 'cpuinfo' tiene modelo y
	 * marca, en ese orden
	 */
	info = cpu_info_new ("cpuinfo/modeltype");

	/* y obtenemos 'Unknown' como marca y modelo */
	fail_unless (biseqcstr (info.type, "Test type"));
	fail_unless (biseqcstr (info.model, "Test model"));
}
END_TEST

START_TEST (test_cpuinfo_other_tags)
{
	/* Debería andar todo bien si el archivo 'cpuinfo' tiene otros valores
	 * además de marca y modelo */
	info = cpu_info_new ("cpuinfo/othertags");

	/* y obtenemos la marca y modelo del archivo */
	fail_unless (biseqcstr (info.type, "Test type"));
	fail_unless (biseqcstr (info.model, "Test model"));
}
END_TEST

START_TEST (test_cpuinfo_any_separator)
{
	/* Debería andar todo bien si el archivo 'cpuinfo' tiene separadores
	 * distintos de "\t: ". En general, cualquier cosa no alfanumérica;
	 * No chequeamos por solo espacios, por que esos no son separador sino
	 * parte de la etiqueta
	 */
	info = cpu_info_new ("cpuinfo/separator");

	/* y obtenemos la marca y modelo del archivo */
	fail_unless (biseqcstr (info.type, "Test type"));
	fail_unless (biseqcstr (info.model, "Test model"));
}
END_TEST

START_TEST (test_cpuinfo_first_cpu)
{
	/* Si en el archivo 'cpuinfo' hay más de una copia de la información
	 * (es normal en equipos multi-CPU/multi-core, se debe tomar la primer
	 * marca y el primer modelo, sin importar si son distintas.
	 */
	info = cpu_info_new ("cpuinfo/firstcpu");

	/* y obtenemos la marca y modelo del archivo */
	fail_unless (biseqcstr (info.type, "Test type"));
	fail_unless (biseqcstr (info.model, "Test model"));
}
END_TEST

START_TEST (test_cpuinfo_blank_lines)
{
	/* Todo anda bien si hay lineas en blanco en el archivo 'cpuinfo'. */
	info = cpu_info_new ("cpuinfo/emptylines");

	/* y obtenemos la marca y modelo del archivo */
	fail_unless (biseqcstr (info.type, "Test type"));
	fail_unless (biseqcstr (info.model, "Test model"));
}
END_TEST

START_TEST (test_cpuinfo_sample_2622)
{
	/* Todo anda bien en un ejemplo sacado de un kernel 2.6.22 */
	info = cpu_info_new ("cpuinfo/sample2.6.22");

	/* y obtenemos la marca y modelo del archivo */
	fail_unless (biseqcstr (info.type, "AuthenticAMD"));
	fail_unless (biseqcstr (info.model, "AMD Athlon(tm) 64 X2 Dual Core Processor 4400+"));
}
END_TEST

START_TEST (test_cpuinfo_destroy)
{
	/* El destructor debería setear los campos a NULL */
	info = cpu_info_new ("cpuinfo/typemodel");
	info = cpu_info_destroy(info);
	fail_unless (info.type == NULL);
	fail_unless (info.model == NULL);
}
END_TEST

static void teardown (void) {
	info = cpu_info_destroy (info);
}

/* Armado de la test suite */

Suite *cpu_info_suite (void)
{
	Suite *s = suite_create ("cpuinfo");
	TCase *tc_preconditions = tcase_create ("Precondition");
	TCase *tc_functionality = tcase_create ("Functionality");
	TCase *tc_destruction = tcase_create ("Destruction");

	/* Precondiciones */
	tcase_add_test_raise_signal (tc_preconditions, test_null_path, SIGABRT);
	suite_add_tcase (s, tc_preconditions);

	/* Funcionalidad */
	tcase_add_checked_fixture (tc_functionality, NULL, teardown);
	tcase_add_test (tc_functionality, test_no_cpuinfo_file);
	tcase_add_test (tc_functionality, test_cpuinfo_empty);
	tcase_add_test (tc_functionality, test_cpuinfo_typeonly);
	tcase_add_test (tc_functionality, test_cpuinfo_modelonly);
	tcase_add_test (tc_functionality, test_cpuinfo_type_and_model);
	tcase_add_test (tc_functionality, test_cpuinfo_model_and_type);
	tcase_add_test (tc_functionality, test_cpuinfo_other_tags);
	tcase_add_test (tc_functionality, test_cpuinfo_any_separator);
	tcase_add_test (tc_functionality, test_cpuinfo_first_cpu);
	tcase_add_test (tc_functionality, test_cpuinfo_blank_lines);
	tcase_add_test (tc_functionality, test_cpuinfo_sample_2622);
	suite_add_tcase (s, tc_functionality);

	/* Destructor */
	tcase_add_test (tc_destruction, test_cpuinfo_destroy);
	suite_add_tcase (s, tc_destruction);
	return s;
}

